home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr05
/
xnot12a.zip
/
W3MEM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-20
|
24KB
|
925 lines
#define MEM_C
#ifndef WIN32 /* whole file */
# include "jam.h"
# include "def.h"
# include "proto.h"
/* THIS MODULE MUST BE BUILT LARGE MODEL BECAUSE I HAVE
* NOT SET THE PROTOTYPES TO BE FAR FOR PARAMS OR RETURN ADDRESSES
*/
# include <memory.h>
/*********************************************************
* Windows memory manglement - local heap list from GlobalAlloc
* for Window 3.1 environment.
*/
#ifdef SHARABLE
# define LOCAL extern
#else
# define LOCAL static
#endif
#define STATIC static
#define PRODUCTION
#define MAX_NEAR 1024
#define W3_MAX_SMALL_BLOCK (8*1024)
void W3memLocalInitialize (void);
void W3memLocalTerminate (void);
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ This functions are externed if this module built as a DLL, else local
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
LOCAL void *W3LocalCheck(void);
LOCAL void W3Free(unsigned char *ptr);
LOCAL unsigned char *W3Malloc (unsigned long num_bytes);
LOCAL unsigned char *W3Calloc (unsigned long count, unsigned long num_bytes);
LOCAL unsigned char *W3Realloc (unsigned char *ptr, unsigned long num_bytes);
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* Prototypes and defines needed for private routines
*
* Unit should be a power of two >= the first power of two larger than a
* freed block
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
#define W3_MEMBLK_UNIT 16
#define W3_MEMBLK_MASK (~(W3_MEMBLK_UNIT-1))
#define W3_MEMBLK_PREFIX (int)(sizeof(int))
#define W3_MEMBLK_SUFFIX (int)(sizeof(int))
#define W3_MEMBLK_OVERHEAD (int)(W3_MEMBLK_PREFIX + W3_MEMBLK_SUFFIX)
#define W3_HEAP_PREFIX \
(int)(sizeof(int)+sizeof(W3_QueEntry)+W3_MEMBLK_OVERHEAD)
#define W3_HEAP_SUFFIX (W3_MEMBLK_OVERHEAD)
#define W3_HEAP_OVERHEAD (W3_HEAP_PREFIX + W3_HEAP_SUFFIX)
#define W3_HEAP_INCREMENT W3_MAX_SMALL_BLOCK + W3_HEAP_OVERHEAD
typedef char W3_Boolean;
typedef struct _que_entry
{
struct _que_entry *next;
struct _que_entry *prev;
} W3_QueEntry;
typedef struct _mem_blk
{
int size; /* Positive - free; Negative - alloc'd */
W3_QueEntry link; /* Start of content for alloc'd block */
int mark; /* Used only in checking free blocks on the heap */
/* Not shown here - a 2-byte size field in the last word of the block */
} W3_MemBlk;
typedef struct _heap
{
int size;
W3_QueEntry link;
char guard [W3_MEMBLK_OVERHEAD]; /* Guards are empty alloc'd memblks */
W3_MemBlk first;
/* Not shown here - an additional guard at the end of the heap */
} W3_Heap;
typedef struct _zone
{
W3_QueEntry avail;
W3_QueEntry heaps;
W3_QueEntry *cur;
struct _zone *next;
#ifdef SHAREABLE
int zone_id;
#endif
} W3_Zone;
/* Private only routines - support for external access points only
*/
STATIC W3_MemBlk *W3FormMemBlk(void *, int);
STATIC W3_MemBlk *W3SplitMemBlk(W3_MemBlk *, int);
STATIC W3_Boolean W3JoinMemBlks(W3_MemBlk *, W3_MemBlk *);
STATIC W3_MemBlk *W3FindMemBlk(W3_QueEntry *, int, W3_QueEntry *);
STATIC void W3InsertMemBlk(W3_MemBlk *, W3_QueEntry *);
STATIC void W3RemoveMemBlk(W3_MemBlk *);
STATIC W3_MemBlk *W3NextMemBlk(W3_MemBlk *);
STATIC W3_MemBlk *W3PrevMemBlk(W3_MemBlk *);
STATIC W3_MemBlk *W3CreateHeap(int, W3_QueEntry *);
STATIC void W3DestroyHeap(W3_Heap *);
STATIC W3_Boolean W3HeapIsEmpty(W3_Heap *);
STATIC void *W3LocalMalloc(int size);
STATIC void *W3LocalRealloc(void *curaddr, int newsize);
STATIC void *W3LocalCalloc (int items, int size);
STATIC void W3LocalFree(void *addr);
STATIC int W3LocalSize(void *addr);
#ifdef SHAREABLE
STATIC W3_Zone *W3FindZone(W3_Zone *root, int id);
STATIC W3_Zone *W3CreateZone (W3_Zone *root, int id);
#else
STATIC W3_Zone *W3CreateZone (W3_Zone *root);
#endif
/* Local type definitions and constants
*/
#define TRUE 1
#define FALSE 0
/* w3__zone points to entire memory mgmt structure
*/
#ifdef SHAREABLE
W3_Zone *w3__zone = NULL;
#else
static W3_Zone *w3__zone = NULL;
#endif
#define W3CheckGlobalInit() {if (w3__zone == NULL) W3memLocalInitialize();}
/* Macros taking parameters */
#define W3_QUEUE_MAKEEMPTY(item) {item.next = &item; item.prev = &item;}
#define W3_ROUNDSIZE(size)\
(((size)+W3_MEMBLK_UNIT-1) & W3_MEMBLK_MASK)
#define W3_MEMBLK_SIZEADDR(blk,size)\
((int *)((char *)(blk)+(size)-W3_MEMBLK_SUFFIX))
#define W3_HEAP_ENDGUARDADDR(heap,size)\
((W3_MemBlk *) ((char *)(heap)+(size)-W3_HEAP_SUFFIX))
/********************* External Initialization points *****************
*/
void W3memLocalInitialize (void) /* this call is optional ifndef SHARABLE */
{
if (w3__zone == NULL)
{
#ifdef SHAREABLE
w3__zone = W3CreateZone (w3__zone, GetCurrentTask());
#else
w3__zone = W3CreateZone (w3__zone);
#endif
}
}
void W3memLocalTerminate(void)
{
W3_Heap *heap;
W3_Zone *zone;
for (zone = w3__zone; zone != NULL; zone = zone->next)
while (zone->heaps.next != &(zone->heaps))
{
heap = (W3_Heap *) ((char *) zone->heaps.next - sizeof(int));
zone->heaps.next = heap->link.next;
W3DestroyHeap (heap);
}
w3__zone = NULL;
}
/********************* Normally private access points, **********************
*/
/* akin to malloc, returns far ptr to memory
*/
LOCAL unsigned char *W3Malloc (unsigned long num_bytes)
{
HANDLE mhnd;
unsigned char *adr;
W3CheckGlobalInit();
mhnd = 0;
if (num_bytes < MAX_NEAR )
adr = W3LocalMalloc ((int)num_bytes);
else
{
mhnd = GlobalAlloc (GMEM_MOVEABLE, num_bytes);
if (mhnd == 0)
return NULL;
adr = (unsigned char *) GlobalLock (mhnd);
}
return adr;
}
/* akin to calloc, returns far ptr to memory
*/
LOCAL unsigned char *W3Calloc (unsigned long count, unsigned long num_bytes)
{
HANDLE mhnd;
unsigned long real_size;
unsigned char *adr;
W3CheckGlobalInit();
real_size = count * num_bytes;
if (real_size < MAX_NEAR )
adr = W3LocalCalloc ((int) count, (int) num_bytes);
else
{
mhnd = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, real_size);
if (mhnd == 0)
return NULL;
adr = (unsigned char *) GlobalLock (mhnd);
}
return adr;
}
/* akin to realloc, returns far ptr to memory
*/
LOCAL unsigned char *W3Realloc (unsigned char *ptr, unsigned long num_bytes)
{
HANDLE mhnd,mhnd2;
char *adr2;
unsigned long move_len;
W3CheckGlobalInit();
if (LOWORD((long)ptr) != 0) /* If memory is not global */
{
if (num_bytes < MAX_NEAR ) /* Both old and new are local handles */
ptr = W3LocalRealloc (ptr, (int) num_bytes);
else
{
move_len = W3LocalSize (ptr);
if ((unsigned long) num_bytes < move_len)
move_len = num_bytes;
mhnd2 = GlobalAlloc (GMEM_MOVEABLE, num_bytes);
if (mhnd2 == 0)
return NULL;
adr2 = (unsigned char *) GlobalLock (mhnd2);
memcpy (adr2, ptr, (int) move_len);
W3LocalFree (ptr);
ptr = adr2;
} /* End of case where new one is too big for local */
} /* End of cases where old block was local */
else /* Always GlobalReAlloc if the memory was originally global */
{
if ((mhnd = LOWORD (GlobalHandle (HIWORD(ptr)))) == 0)
return NULL;
mhnd = GlobalReAlloc (mhnd, num_bytes, GMEM_MOVEABLE);
if (mhnd == 0)
return NULL;
ptr = (unsigned char *) GlobalLock (mhnd);
} /* End of case where old one was global */
return ptr;
}
/* akin to free, returns memory alloced above
*/
LOCAL void W3Free(unsigned char *ptr)
{
HANDLE mhnd;
W3CheckGlobalInit();
if (LOWORD((long)ptr) == 0) /* If memory is global */
{
if ((mhnd = LOWORD (GlobalHandle (HIWORD(ptr)))) == 0)
return ;
if (GlobalFree (mhnd) != 0)
return ;
}
else
W3LocalFree(ptr);
}
/* DEBUG ROUTINE TO CHECK HEAP STATE
*/
LOCAL void *W3LocalCheck()
{
#ifndef PRODUCTION
W3_Zone *zone;
W3_Heap *h;
W3_MemBlk *b;
W3_QueEntry *hq, *q, *prev;
int size;
# ifdef SHAREABLE
zone = W3FindZone (w3__zone);
# else
zone = w3__zone;
# endif
/* Check that blocks haven't overrun other blocks
*/
for (hq = zone->heaps.next; hq != &(zone->heaps); hq = hq->next)
{
h = (W3_Heap *) ((char *)hq - sizeof(int));
for (b = &h->first;
(unsigned long) b <
(unsigned long) W3_HEAP_ENDGUARDADDR (h, h->size);
b = W3NextMemBlk (b))
{
if ((b->size > -16) && (b->size < 16))
return b;
if (b->size > 0)
{
b->mark = 0;
size = b->size;
if ((b->link.prev->next != &b->link) ||
(b->link.next->prev != &b->link))
return b;
}
else
size = -(b->size);
if (*(W3_MEMBLK_SIZEADDR (b, size)) != b->size)
return b;
}
}
/* Check the integrity of the free list, marking free blocks that appear */
prev = &zone->avail;
for (q = prev->next; q != &zone->avail; prev = q, q = q->next)
{
b = (W3_MemBlk *) ((char *)q-W3_MEMBLK_PREFIX);
if (b->size < 16) /* Marked allocated */
return b;
b -> mark = 1;
if (q->prev != prev)
return b;
}
/* Check the integrity of the randomizing pointer */
b = (W3_MemBlk *) ((char *)zone->cur-W3_MEMBLK_PREFIX);
if (!b->mark)
return b;
/* Check for "lost" free nodes, which don't appear in the free list */
for (hq = zone->heaps.next; hq != &zone->heaps; hq = hq->next)
{
h = (W3_Heap *) ((char *)hq - sizeof(int));
for (b = &h->first; (unsigned long) b <
(unsigned long) W3_HEAP_ENDGUARDADDR (h, h->size);
b = W3NextMemBlk (b))
if ((b->size > 0) && (b->mark != 1))
return b;
}
/* The heap passed all tests */
#endif /* PRODUCTION */
return NULL;
}
/************** Private support routines, can't be EXTERNED ****************/
/* make memory into know block
*/
STATIC W3_MemBlk *W3FormMemBlk(void *addr, int size)
{
W3_MemBlk *result;
result = (W3_MemBlk *) addr;
result -> size = -size;
*W3_MEMBLK_SIZEADDR (result,size) = -size;
return result;
}
/* Split a free memory block in two, giving the first the specified size.
*/
STATIC W3_MemBlk *W3SplitMemBlk(W3_MemBlk *block, int size)
{
W3_MemBlk *newblk;
int new_blksize;
if ((block->size <= W3_MEMBLK_OVERHEAD) || (size <= W3_MEMBLK_OVERHEAD))
return NULL;
new_blksize = block->size - size;
newblk = (W3_MemBlk *) ((char *) block + size);
newblk->size = new_blksize;
*W3_MEMBLK_SIZEADDR (newblk,new_blksize) = new_blksize;
newblk->link.prev = &block->link;
newblk->link.next = block->link.next;
newblk->link.next->prev = &newblk->link;
newblk->link.prev->next = &newblk->link;
block->size = size;
*W3_MEMBLK_SIZEADDR (block,size) = size;
return newblk;
}
/* join adjacent memory if possible
*/
STATIC W3_Boolean W3JoinMemBlks(W3_MemBlk *first, W3_MemBlk *second)
{
if (((char *)second != (char *)first + first->size) ||
(second-> size <= W3_MEMBLK_OVERHEAD) ||
(first-> size <= W3_MEMBLK_OVERHEAD))
return FALSE;
second->link.prev->next = second->link.next;
second->link.next->prev = second->link.prev;
first->size += second->size;
*W3_MEMBLK_SIZEADDR (first,first->size) = first->size;
return TRUE;
}
/* find a free blk in heap
*/
STATIC W3_MemBlk *W3FindMemBlk(W3_QueEntry *q, int size,
W3_QueEntry *dummy)
{
W3_QueEntry *p;
W3_MemBlk *curblock;
for (p = q->next; ; p = p->next)
{
if (p != dummy) /* Skip over listhead */
{
curblock = (W3_MemBlk *) ((char *)p-W3_MEMBLK_PREFIX);
if (curblock->size >= size)
return curblock;
}
if (p == q)
break;
}
return NULL;
}
/* insert a block into the free list, marking it as free.
*/
STATIC void W3InsertMemBlk(W3_MemBlk *block, W3_QueEntry *q)
{
block->size = -block->size;
*W3_MEMBLK_SIZEADDR(block,block->size) = block->size;
block->link.next = q;
block->link.prev = q->prev;
block->link.next->prev = &block->link;
block->link.prev->next = &block->link;
}
/* allocate a blk of memory
*/
STATIC void W3RemoveMemBlk(W3_MemBlk *block)
{
block->size = -block->size;
*W3_MEMBLK_SIZEADDR(block,(-block->size)) = block->size;
block->link.prev->next = block->link.next;
block->link.next->prev = block->link.prev;
}
/* find next blk
*/
STATIC W3_MemBlk *W3NextMemBlk(W3_MemBlk *curr)
{
int size;
size = curr->size;
if (size < 0)
size = -size;
return (W3_MemBlk *) ((char *)curr+size);
}
/* find prev blk
*/
STATIC W3_MemBlk *W3PrevMemBlk(W3_MemBlk *curr)
{
int size;
size = *(int *)((char *)curr-W3_MEMBLK_SUFFIX);
if (size < 0)
size = -size;
return (W3_MemBlk *) ((char *)curr-size);
}
/* create a heap, insert into list
*/
STATIC W3_MemBlk *W3CreateHeap(int size, W3_QueEntry *after)
{
W3_Heap *result;
{
HANDLE mhnd;
mhnd = GlobalAlloc (GMEM_MOVEABLE, (unsigned long) size);
if (mhnd == 0)
result = NULL;
else
result = (W3_Heap *) GlobalLock (mhnd);
}
if (result == NULL)
return NULL;
result->size = size;
result->link.prev = after;
result->link.next = after->next;
result->link.next->prev = &result->link;
result->link.prev->next = &result->link;
W3FormMemBlk (&result->guard, W3_MEMBLK_OVERHEAD);
W3FormMemBlk (&result->first, size-W3_HEAP_OVERHEAD);
W3FormMemBlk (W3_HEAP_ENDGUARDADDR(result,size), W3_MEMBLK_OVERHEAD);
return &result->first;
}
/* destroy heap, remove from list
*/
STATIC void W3DestroyHeap(W3_Heap *heap)
{
HANDLE mhnd;
heap->link.prev->next = heap->link.next;
heap->link.next->prev = heap->link.prev;
if ((mhnd = LOWORD (GlobalHandle (HIWORD(heap)))) != 0)
GlobalFree (mhnd);
}
/* return if entire heap is one unused blk
*/
STATIC W3_Boolean W3HeapIsEmpty(W3_Heap *heap)
{
return (W3_Boolean)((heap->first.size) == (heap->size-W3_HEAP_OVERHEAD));
}
#ifdef SHAREABLE
/* find zone of memory with requested if
*/
STATIC W3_Zone *W3FindZone(W3_Zone *root, int id)
{
W3_Zone *zone;
for (zone = root; zone != NULL; zone = zone->next)
if (zone -> zone_id == id)
break;
return zone;
}
#endif
/* create a zone of memory, possible marked with id
*/
#ifdef SHAREABLE
W3_Zone *W3CreateZone (W3_Zone *root, int id)
#else
W3_Zone *W3CreateZone (W3_Zone *root)
#endif
{
W3_Zone *zone;
HANDLE hZone;
if (root == NULL)
{
hZone = LocalAlloc (LMEM_FIXED, sizeof (W3_Zone));
if (hZone == 0)
zone = NULL;
else
zone = (W3_Zone *) (LocalLock (hZone));
}
else
{
for (zone = root; zone->next != NULL; zone = zone->next)
;
hZone = LocalAlloc (LMEM_FIXED, sizeof (W3_Zone));
if (hZone == 0)
zone = NULL;
else
zone -> next = (W3_Zone *) LocalLock (hZone);
zone = zone->next;
}
if (zone == NULL)
return NULL;
zone -> avail.prev = &(zone -> avail);
zone -> avail.next = &(zone -> avail);
zone -> heaps.prev = &(zone -> heaps);
zone -> heaps.next = &(zone -> heaps);
zone -> cur = &(zone -> avail);
zone -> next = NULL;
#ifdef SHAREABLE
zone -> zone_id = id;
#endif
return zone;
}
/* malloc memory from existing stores
*/
STATIC void *W3LocalMalloc(int size)
{
int actsize;
W3_MemBlk *temp;
W3_Zone *zone;
#ifdef SHAREABLE
int zoneid;
zoneid = GetCurrentTask();
if ((zone = W3FindZone (w3__zone, zoneid)) == NULL)
if ((zone = W3CreateZone (w3__zone, zoneid)) == NULL)
return NULL;
#else
if (!(zone = w3__zone))
if ((zone = W3CreateZone (w3__zone)) == NULL)
#endif
if (size > W3_MAX_SMALL_BLOCK-W3_MEMBLK_OVERHEAD)
return NULL;
/* Leave room for overhead and ensure that no tiny fragments
* which are too small to fit on the free list are generated.
*/
actsize = W3_ROUNDSIZE (size + W3_MEMBLK_OVERHEAD);
temp = W3FindMemBlk (zone->cur, actsize, &(zone->avail));
if (temp == NULL)
{
temp = W3CreateHeap (W3_HEAP_INCREMENT, &(zone->heaps));
if (temp == NULL)
return NULL;
W3InsertMemBlk (temp, zone->cur);
}
if (temp->size > actsize + W3_MEMBLK_OVERHEAD) /* If it can be split */
W3SplitMemBlk (temp, actsize);
zone->cur = temp->link.prev;
W3RemoveMemBlk (temp);
return ((void *) (&temp->link));
}
/* realloc memory from existing stores
*/
STATIC void *W3LocalRealloc(void *curaddr, int newsize)
{
W3_MemBlk *curr, *newblk;
W3_Zone *zone;
char *newmem;
int adjsize, incr;
#ifdef SHAREABLE
if ((zone = W3FindZone (w3__zone, GetCurrentTask())) == NULL)
return NULL;
#else
if (!(zone = w3__zone))
return NULL;
#endif
if (newsize > W3_MAX_SMALL_BLOCK-W3_MEMBLK_OVERHEAD)
return NULL;
curr = (W3_MemBlk *) ((char *)curaddr - W3_MEMBLK_PREFIX);
if (curr->size > 0) /* If the block is free, go no further */
return NULL;
adjsize = W3_ROUNDSIZE (newsize + W3_MEMBLK_OVERHEAD);
incr = adjsize - (-curr->size); /* remember - curr->size is negative */
/* If the request is enough less than the current
* allocation, free space
*/
if (incr < 0)
{
curr->size = curr->size - incr;
*W3_MEMBLK_SIZEADDR(curr, -curr->size) = curr->size;
newblk = W3FormMemBlk ((char *)curr - curr->size, -incr);
W3InsertMemBlk (newblk, zone->cur);
}
/* If caller wants more space & the next block is big
* enough & free, use it
*/
if (incr > 0)
{
newblk = W3NextMemBlk (curr);
if (newblk->size > (2 * incr)) /* Too big to sacrifice the whole thing */
W3SplitMemBlk (newblk, incr);
if (newblk->size >= incr)
{
zone->cur = newblk->link.prev;
newblk->link.prev -> next = newblk->link.next;
newblk->link.next -> prev = newblk->link.prev;
curr->size -= newblk->size;
*W3_MEMBLK_SIZEADDR (curr,-curr->size) = curr->size;
}
else /* No such luck. We have to move the data */
{
newmem = W3LocalMalloc (newsize);
if (newmem == NULL)
curaddr = NULL;
else
{
memcpy (newmem, curaddr, (-curr->size)-W3_MEMBLK_OVERHEAD);
W3LocalFree (curaddr);
curaddr = newmem;
}
}
}
/* Case when only a very little is being trimmed is
* handled implicitly i.e. do nothing
*/
return curaddr;
}
/* calloc memory from local stores
*/
STATIC void *W3LocalCalloc (int items, int size)
{
void *temp;
temp = W3LocalMalloc (items * size);
if (temp != NULL)
memset (temp, '\0', items * size);
return temp;
}
/* free memory allocated from local stores
*/
STATIC void W3LocalFree(void *addr)
{
W3_MemBlk *block, *other;
W3_Zone *zone;
W3_Heap *heap;
#ifdef SHAREABLE
if ((zone = W3FindZone (w3__zone, GetCurrentTask())) == NULL)
return;
#else
if (!(zone = w3__zone))
return;
#endif
block = (W3_MemBlk *) ((char *)addr - W3_MEMBLK_PREFIX);
W3InsertMemBlk (block, &(zone->avail));
W3JoinMemBlks(block,
W3NextMemBlk(block)); /* Joins check before joining */
other = W3PrevMemBlk(block); /* so just try it and see */
if (W3JoinMemBlks(other, block))
zone->cur = other->link.next;
else
zone->cur = block->link.next;
heap = (W3_Heap *)((unsigned long)block & 0xFFFF0000L); /* Hack works */
if (W3HeapIsEmpty (heap))
{
W3RemoveMemBlk (&heap->first);
W3DestroyHeap (heap);
}
}
/* return avali size at address
*/
STATIC int W3LocalSize(void *addr)
{
W3_MemBlk *block;
int size;
block = (W3_MemBlk *) ((char *)addr - W3_MEMBLK_PREFIX);
size = (block->size > 0) ? block->size : -block->size;
size -= W3_MEMBLK_OVERHEAD;
return size;
}
/****************************************************************************
* Memory management functions REPLACING C-runtime malloc, calloc,
* realloc and free. Only for use ifndef SHAREABLE. #define MAGIC, etc
* to build guard code during debugging. If this module built as DLL,
* then need to make W3Malloc, W3Calloc, W3Realloc and W3Free calls instead.
*
* Defining MAGIC requires fleshing out localprintf and localbeep (notGNU
* provides entry points when linked/compiled nonshareable into notGNU.exe)
*
*****************************************************************************/
#ifndef SHAREABLE
/* TO TURN ON MEMORY MANAGLEMENT CHECKING...
*/
#define MAGIC 0x4d4d4d4dL
#define OLDMAGIC 0x46464646L
#define CRASH 0x55
#define NEWMEM 0x45
#define localprintf ewprintf
#define localbeep ttbeep
/* COMMENT OUT TO TURN OFF */
/* Struct at head of allocated block. Single GUARD word
* appended at end as well.
*/
typedef unsigned int GUARD;
typedef struct _chunk
{
GUARD magic;
long nbytes;
} Chunk;
#define nChunk sizeof(Chunk)
#define nEnd sizeof(GUARD)
#define Mem(pmem_) (Chunk *)(((char *)pmem_ - nChunk))
#define End(p, q) (GUARD *)((char *)p + q->nbytes)
/* Capture entry points; caller code thinks this is C runtime!
*/
void CDECL free(void FAR *p)
{
#ifdef MAGIC
Chunk *q;
GUARD *eguard;
if (!p)
{
localprintf("Free: pointer is NULL!");
localbeep();
sleep(1);
return;
}
q = Mem(p);
eguard = End(p, q);
if (q->magic != (GUARD)MAGIC)
{
if (q->magic == (GUARD)OLDMAGIC)
localprintf("Free: memory already freed!");
else
localprintf("Free: front guard gone!");
localbeep();
sleep(1);
return;
}
if (*eguard != (GUARD)MAGIC)
{
localprintf("Free: end guard gone!");
localbeep();
sleep(1);
return;
}
memset(p, CRASH, (size_t)q->nbytes); /* make it useless */
q->magic = (GUARD)OLDMAGIC; /* mark freed */
p = q; /* free the real allocated block */
#endif /* MAGIC */
W3Free((unsigned char *)p);
}
void * CDECL malloc(size_t n)
{
#ifdef MAGIC
Chunk *q;
char *p;
q = (Chunk *)W3Malloc((unsigned long)n + nChunk + nEnd);
p = (char *)q;
if (p)
{
GUARD *eguard;
q->magic = (GUARD)MAGIC;
q->nbytes = (long)n;
p += nChunk; /* user pointer value */
eguard = End(p, q);
*eguard = (GUARD)MAGIC;
}
memset(p, NEWMEM, n);
return (p);
#else /* MAGIC */
return (W3Malloc((unsigned long)n));
#endif /* MAGIC */
}
void * CDECL calloc(size_t c, size_t n)
{
#ifdef MAGIC
char *p = malloc(c * n);
if (p)
memset(p, 0, c * n);
return (p);
#else /* MAGIC */
return(W3Calloc((unsigned long)c, (unsigned long)n));
#endif /* MAGIC */
}
void * CDECL realloc(void FAR * p, size_t n)
{
#ifdef MAGIC
Chunk *q;
char *s;
GUARD *eguard;
q = Mem(p);
eguard = End(p, q);
if (q->magic != (GUARD)MAGIC)
{
if (q->magic == (GUARD)OLDMAGIC)
localprintf("Realloc: memory freed!");
else
localprintf("Realloc: no front guard!");
localbeep();
sleep(1);
}
if (*eguard != (GUARD)MAGIC)
{
localprintf("Realloc: no end guard!");
localbeep();
sleep(1);
}
/* cheap, realloc smaller doesn't do anything!
*/
if (q->nbytes <= (long)n)
return(p);
s = malloc(n);
if (!s)
{
free(p);
return(NULL);
}
/* move used bytes to new block, free old block
*/
memcpy(s, p, (size_t)(q->nbytes)); /* know that old size was smaller */
free(q); /* free actual allocated block */
return(s);
#else
return (W3Realloc((unsigned char *)p, (unsigned long)n));
#endif
}
#endif /* ~SHAREABLE */
#endif /* whole file */